﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

using Microsoft.TeamFoundation.VersionControl.Client;

namespace SourceControlAbstraction
{
    public class ChangeAnalysis
    {
        public DateTime PerformedOn { get; protected set; }
        public List<Checkin> Checkins { get; protected set; }
        
        public List<Item> Items { get; protected set; }
        public List<Changeset> Changesets { get; protected set; }

        public ChangeAnalysis()
        {
            PerformedOn = DateTime.Now;
            Checkins = new List<Checkin>();
            Items = new List<Item>();
        }

        public void SetChangesets(List<Changeset> changesets)
        {
            Changesets = changesets;

            // Create the "Before" checkin
            Checkins.Add(new Checkin());

            // Get the list of items and create all the checkins
            Changesets.Sort(new SortOnChangesetNumber());
            foreach (Changeset cs in Changesets)
            {
                foreach (Change c in cs.Changes)
                {
                    if (!Items.Contains(c.Item))
                    {
                        Items.Add(c.Item);
                    }
                }

                Checkins.Add(new Checkin(cs));
            }

            // Create all the changepoints, exept the "Before"
            Items.Sort(new SortOnItemServerPath());
            for (int i = 0; i < Checkins.Count; i++)
            {
                Checkin ci = Checkins[i];

                foreach (Item item in Items)
                {
                    if ((ci.Changeset != null) && (ci.Changeset.Changes.Any(x => x.Item.ServerItem == item.ServerItem)))
                    {
                        ci.Changepoints.Add(new ChangePoint(item, ci.Changeset.Changes.Single(x => x.Item.ServerItem == item.ServerItem)));
                    }
                    else
                    {
                        ci.Changepoints.Add(new ChangePoint(item));
                    }
                }
            }

            // Link all the changepoints to eachother
            for (int i = 0; i < Items.Count; i++)
            {
                for (int j = 0; j < Checkins.Count; j++)
                {
                    if (j > 0)
                    {
                        Checkins[j].Changepoints[i].Previous = Checkins[j - 1].Changepoints[i];
                    }

                    if (j == Checkins.Count - 1)
                    {
                        Checkins[j].Changepoints[i].Next = null;
                    }
                    else
                    {
                        Checkins[j].Changepoints[i].Next = Checkins[j + 1].Changepoints[i];
                    }
                }

                // Change links to only point an active
                for (int j = 0; j < Checkins.Count; j++)
                {
                    ChangePoint currentChangePoint = Checkins[j].Changepoints[i].Next;
                    while ((currentChangePoint != null) && (currentChangePoint.Change == null))
                    {
                        currentChangePoint = currentChangePoint.Next;
                    }
                    Checkins[j].Changepoints[i].Next = currentChangePoint;
                }

                for (int j = Checkins.Count - 1; j >= 0; j--)
                {
                    ChangePoint currentChangePoint = Checkins[j].Changepoints[i].Previous;
                    while ((currentChangePoint != null) && (currentChangePoint.Change == null))
                    {
                        currentChangePoint = currentChangePoint.Previous;
                    }
                    Checkins[j].Changepoints[i].Previous = currentChangePoint;
                }
            }
        }

        public class SortOnItemServerPath : IComparer<Item>
        {
            public int Compare(Item a, Item b)
            {
                return a.ServerItem.CompareTo(b.ServerItem);
            }
        }

        public class SortOnChangesetNumber : IComparer<Changeset>
        {
            public int Compare(Changeset a, Changeset b)
            {
                if (a.ChangesetId > b.ChangesetId) return 1;
                else if (a.ChangesetId < b.ChangesetId) return -1;
                else return 0;
            }
        }
    }
}
